##
#
# Snaarpy: Guitar chord parser and formatter
# Copyright (C) 2009 Alberto Gonzalez
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
##

class Visitable():
    def accept(self, visitor):
        pass

class ModelVisitor(object):
    def beginSong(self, song):
        pass

    def endSong(self, song):
        pass
    
    def songChords(self, chord):
        pass
    
    def beginSongBody(self, song):
        pass
    
    def endSongBody(self, song):
        pass
    
    def beginGroup(self, group):
        pass
    
    def endGroup(self, group):
        pass
    
    def beginInstrumental(self, instrumental):
        pass
    
    def endInstrumental(self, instrumental):
        pass
    
    def beginVerse(self, verse):
        pass
    
    def endVerse(self, verse):
        pass
    
    def text(self, text):
        pass
    
    def chordUse(self, chord, over_text=True):
        pass

class Song(Visitable):
    def __init__(self, title=None, artist=None, capo=None):
        self.title = title
        self.artist = artist
        self.capo = capo
        self.chords = {}
        self.groups = []

    def accept(self, visitor):
        visitor.beginSong(self)
        visitor.songChords(self.chords.values())
        visitor.beginSongBody(self)
        for group in self.groups:
            group.accept(visitor)
        visitor.endSongBody(self)
        visitor.endSong(self)

class Chord(Visitable):
    def __init__(self, short, frets=None):
        self.short = short
        self.frets = frets
    
    def accept(self, visitor):
        visitor.chord(self)

class Group(Visitable):
    def __init__(self, label=None):
        self.label = label
        self.verses = []
    
    def accept(self, visitor):
        visitor.beginGroup(self)
        for verse in self.verses:
            verse.accept(visitor)
        visitor.endGroup(self)

class Instrumental(Visitable):
    def __init__(self, label=None):
        self.label = label
        self.chunks = []
    
    def chords(self):
        return self.chunks
    
    def accept(self, visitor):
        visitor.beginInstrumental(self)
        for chunk in self.chunks:
            chunk.accept(visitor)
        visitor.endInstrumental(self)

class Verse(Visitable):
    def __init__(self):
        self.chunks = []
    
    def chords(self):
        return [c for c in self.chunks if isinstance(c, ChordUse)]
    
    def accept(self, visitor):
        visitor.beginVerse(self)
        for chunk in self.chunks:
            chunk.accept(visitor)
        visitor.endVerse(self)

class Text(Visitable):
    def __init__(self, text):
        self.text = text
    
    def accept(self, visitor):
        visitor.text(self)

class ChordUse(Visitable):
    def __init__(self, chord, word=None):
        self.chord = chord
        self.word = word
    
    def accept(self, visitor):
        visitor.chordUse(self, not self.word == None)
        